//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package fs_api_serv

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/dao/bulletin_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/fs_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/idea_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/issue_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/org_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/project_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/project_doc_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/project_entry_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/requirement_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/roadmap_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/testcase_dao"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/fs_api"
)

type _FsPermCheck struct{}

func (fpc *_FsPermCheck) CheckAllowRead(ctx context.Context, userId string, fsItem *fs_dao.FsInfoDbItem, fileItem *fs_dao.FileInfoDbItem) (bool, error) {
	if fpc == nil || fsItem == nil || fileItem == nil {
		return false, nil
	}
	if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_PROJECT) {
		return fpc.checkProjectRead(ctx, userId, fsItem.OwnerId, fileItem)
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_USER) {
		return userId == fsItem.OwnerId, nil
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_GLOBAL) {
		if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_ROADMAP) {
			roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, fileItem.OwnerId)
			if err != nil {
				return false, err
			}
			if roadmapItem.PubState || roadmapItem.OwnerUserId == userId {
				return true, nil
			}
		} else {
			return true, nil
		}
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_ORG) {
		return org_dao.MemberDao.Exist(ctx, fsItem.OwnerId, userId)
	}
	return false, nil
}

func (fpc *_FsPermCheck) checkProjectRead(ctx context.Context, userId, projectId string, fileItem *fs_dao.FileInfoDbItem) (bool, error) {
	if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_ISSUE) || fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_PROJECT) || fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_NONE) {
		return project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	} else if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_PROJECT_DOC) {
		return project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	} else if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_PAGES) {
		return project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	} else if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_REQUIRE_MENT) {
		exist, err := project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
		if err != nil {
			return false, err
		}
		if !exist {
			return false, nil
		}
		return requirement_dao.RequirementInfoDao.Exist(ctx, projectId, fileItem.OwnerId)
	} else if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_IDEA) {
		return project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	} else if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_BULLETIN) {
		return project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	} else if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_API_COLL) {
		return project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	} else if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_TEST_CASE) {
		return project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	} else if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_TEST_RESULT) {
		return project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	}
	return false, nil
}

func (fpc *_FsPermCheck) CheckAllowWrite(ctx context.Context, userId string, fsItem *fs_dao.FsInfoDbItem, reqFsId string) (bool, error) {
	if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_PROJECT) {
		return project_dao.MemberInfoDao.Exist(ctx, fsItem.OwnerId, userId)
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_USER) {
		return userId == fsItem.OwnerId, nil
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_ORG) {
		return org_dao.MemberDao.Exist(ctx, fsItem.OwnerId, userId)
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_GLOBAL) {
		if reqFsId == "globalGrowCenter" {
			return true, nil
		}
	}
	return false, nil
}

func (fpc *_FsPermCheck) CheckAllowSetOwner(ctx context.Context, userId string, fsItem *fs_dao.FsInfoDbItem,
	fileItem *fs_dao.FileInfoDbItem, ownerType fs_api.FILE_OWNER_TYPE, ownerId string) (bool, error) {
	if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_PROJECT) {
		if fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_NONE) ||
			fileItem.OwnerType == int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_PROJECT) {
			return fpc.checkAllowProjectSetOwner(ctx, userId, fsItem.OwnerId, ownerType, ownerId)
		}
		return false, nil
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_USER) {
		if fileItem.OwnerType != int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_NONE) {
			return false, nil
		}
		return fpc.checkAllowUserSetOwner(userId, fsItem.OwnerId, ownerType)
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_ORG) {
		if fileItem.OwnerType != int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_NONE) {
			return false, nil
		}
		if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_ORG_FORUM_CONTENT {
			contentItem, err := org_dao.ThreadContentDao.SimpleGet(ctx, fsItem.OwnerId, ownerId)
			if err != nil {
				return false, err
			}
			return contentItem.UserId == userId, nil
		}
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_GLOBAL) {
		if fileItem.OwnerType != int32(fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_NONE) {
			return false, nil
		}
		if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_ROADMAP {
			roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, ownerId)
			if err != nil {
				return false, err
			}
			if roadmapItem.OwnerUserId == userId {
				return true, nil
			}
		}
	}
	return false, nil
}

func (fpc *_FsPermCheck) checkAllowProjectSetOwner(ctx context.Context, userId, projectId string, ownerType fs_api.FILE_OWNER_TYPE, ownerId string) (bool, error) {
	memberExist, err := project_dao.MemberInfoDao.Exist(ctx, projectId, userId)
	if err != nil {
		return false, err
	}
	if !memberExist {
		return false, nil
	}
	if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_ISSUE {
		return issue_dao.IssueDao.Exist(ctx, projectId, ownerId)
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_PROJECT {
		return true, nil
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_PROJECT_DOC {
		return project_doc_dao.DocContentDao.Exist(ctx, ownerId)
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_PAGES {
		return project_entry_dao.EntryDao.Exist(ctx, ownerId, projectId)
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_REQUIRE_MENT {
		return requirement_dao.RequirementInfoDao.Exist(ctx, projectId, ownerId)
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_IDEA {
		return idea_dao.IdeaDao.Exist(ctx, projectId, ownerId)
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_BULLETIN {
		return bulletin_dao.BulletinInfoDao.Exist(ctx, ownerId, projectId)
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_API_COLL {
		return project_entry_dao.EntryDao.Exist(ctx, ownerId, projectId)
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_TEST_CASE {
		return testcase_dao.CaseInfoDao.Exist(ctx, ownerId, projectId)
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_TEST_RESULT {
		return testcase_dao.ResultDao.Exist(ctx, projectId, ownerId)
	}
	return false, nil
}

func (fpc *_FsPermCheck) checkAllowUserSetOwner(userId, ownerUserId string, ownerType fs_api.FILE_OWNER_TYPE) (bool, error) {
	if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_USER_PHOTO {
		return userId == ownerUserId, nil
	} else if ownerType == fs_api.FILE_OWNER_TYPE_FILE_OWNER_TYPE_USER_MEMO {
		return userId == ownerUserId, nil
	}
	return false, nil
}

func (fpc *_FsPermCheck) CheckAllowStatFs(ctx context.Context, userId string, fsItem *fs_dao.FsInfoDbItem) (bool, error) {
	if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_PROJECT) {
		return project_dao.MemberInfoDao.Exist(ctx, fsItem.OwnerId, userId)
	} else if fsItem.OwnerType == int32(fs_api.FS_OWNER_TYPE_FS_OWNER_TYPE_USER) {
		return userId == fsItem.OwnerId, nil
	}
	return false, nil
}
